window: Derive from GtkWidget
authorMatthias Clasen <mclasen@redhat.com>
Sat, 2 May 2020 19:17:20 +0000 (15:17 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Tue, 5 May 2020 02:53:08 +0000 (22:53 -0400)
We want to remove GtkBin and GtkContainer as they don't
provide much useful functionality anymore. This requires
us to move get_request_mode and compute_expand down.

Update the accessible implementation to match, remove
remnants of container implementations in GtkWindow
subclasses, and fix livecycle issues around destroy
vs dispose in GtkAssistant.

After this commit, using gtk_container_add on window
subclasses is not allowed anymore, but adding childing
with <child> in ui files still works.

See #2681

gtk/a11y/gtkwindowaccessible.c
gtk/gtkapplicationwindow.c
gtk/gtkassistant.c
gtk/gtkshortcutswindow.c
gtk/gtkwindow.c
gtk/gtkwindow.h
gtk/ui/gtkassistant.ui

index 742cfd2776108b2a7f20d0c8cf4c69a2e3170f97..b25eeffb9654deef919c325c0ac276e24e983442 100644 (file)
@@ -46,7 +46,7 @@ static void atk_window_interface_init (AtkWindowIface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (GtkWindowAccessible,
                          gtk_window_accessible,
-                         GTK_TYPE_CONTAINER_ACCESSIBLE,
+                         GTK_TYPE_WIDGET_ACCESSIBLE,
                          G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT,
                                                 atk_component_interface_init)
                          G_IMPLEMENT_INTERFACE (ATK_TYPE_WINDOW,
@@ -76,33 +76,6 @@ gtk_window_accessible_notify_gtk (GObject    *obj,
     GTK_WIDGET_ACCESSIBLE_CLASS (gtk_window_accessible_parent_class)->notify_gtk (obj, pspec);
 }
 
-static GtkWidget *
-find_label_child (GtkContainer *container)
-{
-  GList *children, *tmp_list;
-  GtkWidget *child;
-
-  children = gtk_container_get_children (container);
-
-  child = NULL;
-  for (tmp_list = children; tmp_list != NULL; tmp_list = tmp_list->next)
-    {
-      if (GTK_IS_LABEL (tmp_list->data))
-        {
-          child = GTK_WIDGET (tmp_list->data);
-          break;
-        }
-      else if (GTK_IS_CONTAINER (tmp_list->data))
-        {
-          child = find_label_child (GTK_CONTAINER (tmp_list->data));
-          if (child)
-            break;
-        }
-   }
-  g_list_free (children);
-  return child;
-}
-
 static const gchar *
 gtk_window_accessible_get_name (AtkObject *accessible)
 {
@@ -236,29 +209,19 @@ gtk_window_accessible_ref_state_set (AtkObject *accessible)
   return state_set;
 }
 
-static void
-count_widget (GtkWidget *widget,
-              gint      *count)
-{
-  (*count)++;
-}
-
-static void
-prepend_widget (GtkWidget  *widget,
-               GList     **list)
-{
-  *list = g_list_prepend (*list, widget);
-}
-
 static gint
 gtk_window_accessible_get_n_children (AtkObject *object)
 {
   GtkWidget *window;
+  GtkWidget *child;
   gint count = 0;
 
   window = gtk_accessible_get_widget (GTK_ACCESSIBLE (object));
-  gtk_container_forall (GTK_CONTAINER (window),
-                       (GtkCallback) count_widget, &count);
+  for (child = gtk_widget_get_first_child (GTK_WIDGET (window));
+       child != NULL;
+       child = gtk_widget_get_next_sibling (child))
+    count++;
+
   return count;
 }
 
@@ -266,19 +229,19 @@ static AtkObject *
 gtk_window_accessible_ref_child (AtkObject *object,
                                  gint       i)
 {
-  GtkWidget *window, *ref_child;
-  GList *children = NULL;
+  GtkWidget *window, *child;
+  int pos;
 
   window = gtk_accessible_get_widget (GTK_ACCESSIBLE (object));
-  gtk_container_forall (GTK_CONTAINER (window),
-                       (GtkCallback) prepend_widget, &children);
-  ref_child = g_list_nth_data (children, i);
-  g_list_free (children);
-
-  if (!ref_child)
-    return NULL;
+  for (child = gtk_widget_get_first_child (GTK_WIDGET (window)), pos = 0;
+       child != NULL;
+       child = gtk_widget_get_next_sibling (child), pos++)
+    {
+      if (pos == i)
+        return g_object_ref (gtk_widget_get_accessible (child));
+    }
 
-  return g_object_ref (gtk_widget_get_accessible (ref_child));
+  return NULL;
 }
 
 static void
index 6f17e65f3f2da20895d2e89c537cf7563be418c0..4afc2910a6b87b0199063b3cb8011a7ee51566f1 100644 (file)
@@ -591,7 +591,7 @@ gtk_application_window_real_size_allocate (GtkWidget *widget,
 
       child_allocation.y += menubar_height;
       child_allocation.height -= menubar_height;
-      child = gtk_bin_get_child (GTK_BIN (window));
+      child = gtk_window_get_child (GTK_WINDOW (window));
       if (child != NULL && gtk_widget_get_visible (child))
         gtk_widget_size_allocate (child, &child_allocation, baseline);
     }
@@ -668,21 +668,6 @@ gtk_application_window_real_unmap (GtkWidget *widget)
   GTK_WIDGET_CLASS (gtk_application_window_parent_class)->unmap (widget);
 }
 
-static void
-gtk_application_window_real_forall_internal (GtkContainer *container,
-                                             GtkCallback   callback,
-                                             gpointer      user_data)
-{
-  GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (container);
-  GtkApplicationWindowPrivate *priv = gtk_application_window_get_instance_private (window);
-
-  if (priv->menubar)
-    callback (priv->menubar, user_data);
-
-  GTK_CONTAINER_CLASS (gtk_application_window_parent_class)
-    ->forall (container, callback, user_data);
-}
-
 static void
 gtk_application_window_get_property (GObject    *object,
                                      guint       prop_id,
@@ -782,12 +767,9 @@ gtk_application_window_init (GtkApplicationWindow *window)
 static void
 gtk_application_window_class_init (GtkApplicationWindowClass *class)
 {
-  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
   GObjectClass *object_class = G_OBJECT_CLASS (class);
 
-  container_class->forall = gtk_application_window_real_forall_internal;
-
   widget_class->measure = gtk_application_window_measure;
   widget_class->size_allocate = gtk_application_window_real_size_allocate;
   widget_class->realize = gtk_application_window_real_realize;
index c0b00dbf8fe297270134d99b5720cb0f43fef764..607f010ca9b1e0dc196750c0553a2da06db03483 100644 (file)
@@ -159,15 +159,11 @@ struct _GtkAssistantPrivate
   guint committed : 1;
 };
 
-static void     gtk_assistant_destroy            (GtkWidget         *widget);
+static void     gtk_assistant_dispose            (GObject           *object);
 static void     gtk_assistant_map                (GtkWidget         *widget);
 static void     gtk_assistant_unmap              (GtkWidget         *widget);
 static gboolean gtk_assistant_close_request      (GtkWindow         *window);
 
-static void     gtk_assistant_add                (GtkContainer      *container,
-                                                  GtkWidget         *page);
-static void     gtk_assistant_remove             (GtkContainer      *container,
-                                                  GtkWidget         *page);
 static void     gtk_assistant_page_set_property  (GObject           *object,
                                                   guint              property_id,
                                                   const GValue      *value,
@@ -208,10 +204,6 @@ static void     on_assistant_cancel                      (GtkWidget          *wi
                                                           GtkAssistant       *assistant);
 static void     on_assistant_last                        (GtkWidget          *widget,
                                                           GtkAssistant       *assistant);
-static void     assistant_remove_page_cb                 (GtkContainer       *container,
-                                                          GtkWidget          *page,
-                                                          GtkAssistant       *assistant);
-
 
 static int        gtk_assistant_add_page                 (GtkAssistant     *assistant,
                                                           GtkAssistantPage *page_info,
@@ -507,28 +499,23 @@ gtk_assistant_class_init (GtkAssistantClass *class)
 {
   GObjectClass *gobject_class;
   GtkWidgetClass *widget_class;
-  GtkContainerClass *container_class;
   GtkWindowClass *window_class;
 
   gobject_class   = (GObjectClass *) class;
   widget_class    = (GtkWidgetClass *) class;
-  container_class = (GtkContainerClass *) class;
   window_class    = (GtkWindowClass *) class;
 
+  gobject_class->dispose = gtk_assistant_dispose;
   gobject_class->finalize = gtk_assistant_finalize;
   gobject_class->constructed  = gtk_assistant_constructed;
   gobject_class->set_property = gtk_assistant_set_property;
   gobject_class->get_property = gtk_assistant_get_property;
 
-  widget_class->destroy = gtk_assistant_destroy;
   widget_class->map = gtk_assistant_map;
   widget_class->unmap = gtk_assistant_unmap;
 
   gtk_widget_class_set_accessible_type (widget_class, _gtk_assistant_accessible_get_type ());
 
-  container_class->add = gtk_assistant_add;
-  container_class->remove = gtk_assistant_remove;
-
   window_class->close_request = gtk_assistant_close_request;
 
   /**
@@ -665,7 +652,6 @@ gtk_assistant_class_init (GtkAssistantClass *class)
   gtk_widget_class_bind_template_child_private (widget_class, GtkAssistant, button_size_group);
   gtk_widget_class_bind_template_child_private (widget_class, GtkAssistant, title_size_group);
 
-  gtk_widget_class_bind_template_callback (widget_class, assistant_remove_page_cb);
   gtk_widget_class_bind_template_callback (widget_class, on_assistant_close);
   gtk_widget_class_bind_template_callback (widget_class, on_assistant_apply);
   gtk_widget_class_bind_template_callback (widget_class, on_assistant_forward);
@@ -1134,9 +1120,8 @@ on_page_notify (GtkAssistantPage *page,
 }
 
 static void
-assistant_remove_page_cb (GtkContainer *container,
-                          GtkWidget    *page,
-                          GtkAssistant *assistant)
+assistant_remove_page (GtkAssistant *assistant,
+                       GtkWidget    *page)
 {
   GtkAssistantPrivate *priv = gtk_assistant_get_instance_private (assistant);
   GtkAssistantPage *page_info;
@@ -1337,9 +1322,9 @@ gtk_assistant_page_get_property (GObject      *object,
 }
 
 static void
-gtk_assistant_destroy (GtkWidget *widget)
+gtk_assistant_dispose (GObject *object)
 {
-  GtkAssistant *assistant = GTK_ASSISTANT (widget);
+  GtkAssistant *assistant = GTK_ASSISTANT (object);
   GtkAssistantPrivate *priv = gtk_assistant_get_instance_private (assistant);
 
   if (priv->model)
@@ -1352,27 +1337,14 @@ gtk_assistant_destroy (GtkWidget *widget)
 
   if (priv->content)
     {
-      GList *children, *l;
-
-      children = gtk_container_get_children (GTK_CONTAINER (priv->content));
-      for (l = children; l; l = l->next)
-        {
-          GtkWidget *page = l->data;
-          gtk_container_remove (GTK_CONTAINER (priv->content), page);
-        }
-      g_list_free (children);
-
-      /* Our GtkAssistantPage list should be empty now. */
-      g_warn_if_fail (priv->pages == NULL);
+      while (priv->pages)
+        gtk_assistant_remove_page (assistant, 0);
 
       priv->content = NULL;
     }
 
-  if (priv->sidebar)
-    priv->sidebar = NULL;
-
-  if (priv->action_area)
-    priv->action_area = NULL;
+  priv->sidebar = NULL;
+  priv->action_area = NULL;
 
   if (priv->forward_function)
     {
@@ -1391,8 +1363,7 @@ gtk_assistant_destroy (GtkWidget *widget)
       priv->visited_pages = NULL;
     }
 
-  gtk_window_set_titlebar (GTK_WINDOW (widget), NULL);
-  GTK_WIDGET_CLASS (gtk_assistant_parent_class)->destroy (widget);
+  G_OBJECT_CLASS (gtk_assistant_parent_class)->dispose (object);
 }
 
 static GList*
@@ -1478,47 +1449,6 @@ gtk_assistant_close_request (GtkWindow *window)
   return TRUE;
 }
 
-static void
-gtk_assistant_add (GtkContainer *container,
-                   GtkWidget    *page)
-{
-  GtkAssistant *assistant = GTK_ASSISTANT (container);
-  GtkAssistantPrivate *priv = gtk_assistant_get_instance_private (assistant);
-
-  /* A bit tricky here, GtkAssistant doesnt exactly play by 
-   * the rules by allowing gtk_container_add() to insert pages.
-   *
-   * For the first invocation (from the builder template invocation),
-   * let's make sure we add the actual direct container content properly.
-   */
-  if (!priv->constructed)
-    {
-      gtk_widget_set_parent (page, GTK_WIDGET (container));
-      _gtk_bin_set_child (GTK_BIN (container), page);
-      return;
-    }
-
-  gtk_assistant_append_page (GTK_ASSISTANT (container), page);
-}
-
-static void
-gtk_assistant_remove (GtkContainer *container,
-                      GtkWidget    *page)
-{
-  GtkAssistant *assistant = GTK_ASSISTANT (container);
-  GtkAssistantPrivate *priv = gtk_assistant_get_instance_private (assistant);
-
-  /* Forward this removal to the content stack */
-  if (gtk_widget_get_parent (page) == priv->content)
-    {
-      gtk_container_remove (GTK_CONTAINER (priv->content), page);
-    }
-  else
-    {
-      GTK_CONTAINER_CLASS (gtk_assistant_parent_class)->remove (container, page);
-    }
-}
-
 /**
  * gtk_assistant_new:
  *
@@ -1875,9 +1805,8 @@ gtk_assistant_remove_page (GtkAssistant *assistant,
   g_return_if_fail (GTK_IS_ASSISTANT (assistant));
 
   page = gtk_assistant_get_nth_page (assistant, page_num);
-
   if (page)
-    gtk_container_remove (GTK_CONTAINER (assistant), page);
+    assistant_remove_page (assistant, page);
 
   if (priv->model)
     g_list_model_items_changed (priv->model, page_num, 1, 0);
@@ -2322,6 +2251,7 @@ static void
 gtk_assistant_buildable_interface_init (GtkBuildableIface *iface)
 {
   parent_buildable_iface = g_type_interface_peek_parent (iface);
+
   iface->custom_tag_start = gtk_assistant_buildable_custom_tag_start;
   iface->custom_finished = gtk_assistant_buildable_custom_finished;
   iface->add_child = gtk_assistant_buildable_add_child;
@@ -2342,10 +2272,8 @@ gtk_assistant_buildable_add_child (GtkBuildable *buildable,
       priv->headerbar = GTK_WIDGET (child);
       gtk_window_set_titlebar (GTK_WINDOW (buildable), priv->headerbar);
     }
-  else if (GTK_IS_WIDGET (child))
-    gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
   else
-    g_warning ("Can't add a child of type '%s' to '%s'", G_OBJECT_TYPE_NAME (child), G_OBJECT_TYPE_NAME (buildable));
+    parent_buildable_iface->add_child (buildable, builder, child, type);
 }
 
 gboolean
index 375086e15956bb4b149c776287ebdd15a014a3eb..e98644fb0926beb037ca163cecfd96de7a84be1b 100644 (file)
@@ -21,6 +21,7 @@
 #include "gtkshortcutswindowprivate.h"
 
 #include "gtkbox.h"
+#include "gtkbuildable.h"
 #include "gtkgrid.h"
 #include "gtkheaderbar.h"
 #include "gtkintl.h"
@@ -133,8 +134,13 @@ typedef struct
   guint              translatable : 1;
 } ViewsParserData;
 
+static void gtk_shortcuts_window_buildable_iface_init (GtkBuildableIface *iface);
 
-G_DEFINE_TYPE_WITH_PRIVATE (GtkShortcutsWindow, gtk_shortcuts_window, GTK_TYPE_WINDOW)
+
+G_DEFINE_TYPE_WITH_CODE (GtkShortcutsWindow, gtk_shortcuts_window, GTK_TYPE_WINDOW,
+                         G_ADD_PRIVATE (GtkShortcutsWindow)
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                                gtk_shortcuts_window_buildable_iface_init))
 
 
 enum {
@@ -368,62 +374,27 @@ gtk_shortcuts_window_add_section (GtkShortcutsWindow  *self,
   g_free (title);
 }
 
-static void
-gtk_shortcuts_window_add (GtkContainer *container,
-                          GtkWidget    *widget)
-{
-  GtkShortcutsWindow *self = (GtkShortcutsWindow *)container;
-
-  if (GTK_IS_SHORTCUTS_SECTION (widget))
-    gtk_shortcuts_window_add_section (self, GTK_SHORTCUTS_SECTION (widget));
-  else
-    g_warning ("Can't add children of type %s to %s",
-               G_OBJECT_TYPE_NAME (widget),
-               G_OBJECT_TYPE_NAME (container));
-}
+static GtkBuildableIface *parent_buildable_iface;
 
 static void
-gtk_shortcuts_window_remove (GtkContainer *container,
-                             GtkWidget    *widget)
-{
-  GtkShortcutsWindow *self = (GtkShortcutsWindow *)container;
-  GtkShortcutsWindowPrivate *priv = gtk_shortcuts_window_get_instance_private (self);
-
-  g_signal_handlers_disconnect_by_func (widget, section_notify_cb, self);
-
-  if (widget == (GtkWidget *)priv->header_bar ||
-      widget == (GtkWidget *)priv->main_box)
-    GTK_CONTAINER_CLASS (gtk_shortcuts_window_parent_class)->remove (container, widget);
+gtk_shortcuts_window_buildable_add_child (GtkBuildable *buildable,
+                                          GtkBuilder   *builder,
+                                          GObject      *child,
+                                          const gchar  *type)
+{
+  if (GTK_IS_SHORTCUTS_SECTION (child))
+    gtk_shortcuts_window_add_section (GTK_SHORTCUTS_WINDOW (buildable),
+                                      GTK_SHORTCUTS_SECTION (child));
   else
-    gtk_container_remove (GTK_CONTAINER (priv->stack), widget);
+    parent_buildable_iface->add_child (buildable, builder, child, type);
 }
 
 static void
-gtk_shortcuts_window_forall (GtkContainer *container,
-                             GtkCallback   callback,
-                             gpointer      callback_data)
+gtk_shortcuts_window_buildable_iface_init (GtkBuildableIface *iface)
 {
-  GtkShortcutsWindow *self = (GtkShortcutsWindow *)container;
-  GtkShortcutsWindowPrivate *priv = gtk_shortcuts_window_get_instance_private (self);
-
-  if (priv->stack)
-    {
-      GList *children, *l;
-      GtkWidget *search;
-      GtkWidget *empty;
-
-      search = gtk_stack_get_child_by_name (GTK_STACK (priv->stack), "internal-search");
-      empty = gtk_stack_get_child_by_name (GTK_STACK (priv->stack), "no-search-results");
-      children = gtk_container_get_children (GTK_CONTAINER (priv->stack));
-      for (l = children; l; l = l->next)
-        {
-          GtkWidget *child = l->data;
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
 
-          if (child != search && child != empty)
-            callback (child, callback_data);
-        }
-      g_list_free (children);
-    }
+  iface->add_child = gtk_shortcuts_window_buildable_add_child;
 }
 
 static void
@@ -482,7 +453,14 @@ update_accels_for_actions (GtkShortcutsWindow *self)
   GtkShortcutsWindowPrivate *priv = gtk_shortcuts_window_get_instance_private (self);
 
   if (priv->window)
-    gtk_container_forall (GTK_CONTAINER (self), update_accels_cb, self);
+    {
+      GtkWidget *child;
+
+      for (child = gtk_widget_get_first_child (GTK_WIDGET (self));
+           child != NULL;
+           child = gtk_widget_get_next_sibling (child))
+        update_accels_cb (child, self);
+    }
 }
 
 static void
@@ -672,20 +650,9 @@ gtk_shortcuts_window_dispose (GObject *object)
 
   gtk_shortcuts_window_set_window (self, NULL);
 
-  if (priv->header_bar)
-    {
-      gtk_container_remove (GTK_CONTAINER (self), GTK_WIDGET (priv->header_bar));
-      priv->header_bar = NULL;
-      priv->popover = NULL;
-    }
-
-  if (priv->main_box)
-    {
-      gtk_container_remove (GTK_CONTAINER (self), GTK_WIDGET (priv->main_box));
-      priv->main_box = NULL;
-      priv->stack = NULL;
-      priv->search_bar = NULL;
-    }
+  priv->stack = NULL;
+  priv->search_bar = NULL;
+  priv->main_box = NULL;
 
   G_OBJECT_CLASS (gtk_shortcuts_window_parent_class)->dispose (object);
 }
@@ -761,18 +728,11 @@ gtk_shortcuts_window_unmap (GtkWidget *widget)
   GTK_WIDGET_CLASS (gtk_shortcuts_window_parent_class)->unmap (widget);
 }
 
-static GType
-gtk_shortcuts_window_child_type (GtkContainer *container)
-{
-  return GTK_TYPE_SHORTCUTS_SECTION;
-}
-
 static void
 gtk_shortcuts_window_class_init (GtkShortcutsWindowClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
 
   object_class->constructed = gtk_shortcuts_window_constructed;
   object_class->finalize = gtk_shortcuts_window_finalize;
@@ -781,10 +741,6 @@ gtk_shortcuts_window_class_init (GtkShortcutsWindowClass *klass)
   object_class->dispose = gtk_shortcuts_window_dispose;
 
   widget_class->unmap = gtk_shortcuts_window_unmap;
-  container_class->add = gtk_shortcuts_window_add;
-  container_class->remove = gtk_shortcuts_window_remove;
-  container_class->child_type = gtk_shortcuts_window_child_type;
-  container_class->forall = gtk_shortcuts_window_forall;
 
   klass->close = gtk_shortcuts_window_close;
   klass->search = gtk_shortcuts_window_search;
@@ -899,10 +855,9 @@ gtk_shortcuts_window_init (GtkShortcutsWindow *self)
   priv->main_box = g_object_new (GTK_TYPE_BOX,
                            "orientation", GTK_ORIENTATION_VERTICAL,
                            NULL);
-  GTK_CONTAINER_CLASS (gtk_shortcuts_window_parent_class)->add (GTK_CONTAINER (self), GTK_WIDGET (priv->main_box));
+  gtk_window_set_child (GTK_WINDOW (self), priv->main_box);
 
-  priv->search_bar = g_object_new (GTK_TYPE_SEARCH_BAR,
-                                   NULL);
+  priv->search_bar = g_object_new (GTK_TYPE_SEARCH_BAR, NULL);
   g_object_bind_property (priv->search_bar, "search-mode-enabled",
                           search_button, "active",
                           G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
index e18d46a0c2d45d7c30eb67d2cf592a3d182754e3..fbf0a065b7ba3623b4f34aa956b35c452d6ab2ea 100644 (file)
 
 typedef struct
 {
+  GtkWidget             *child;
+
   GtkWidget             *attach_widget;
   GtkWidget             *default_widget;
   GtkWidget             *focus_widget;
@@ -399,11 +401,6 @@ static gboolean surface_event             (GdkSurface         *surface,
                                            GdkEvent           *event,
                                            GtkWidget          *widget);
 
-static void gtk_window_remove             (GtkContainer      *container,
-                                           GtkWidget         *widget);
-static void gtk_window_forall             (GtkContainer   *container,
-                                          GtkCallback     callback,
-                                          gpointer        callback_data);
 static gint gtk_window_focus              (GtkWidget        *widget,
                                           GtkDirectionType  direction);
 static void gtk_window_move_focus         (GtkWidget         *widget,
@@ -542,7 +539,7 @@ static GtkWindowRegion get_active_region_type (GtkWindow   *window,
                                                gint         y);
 
 
-G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
+G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_WIDGET,
                          G_ADD_PRIVATE (GtkWindow)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                gtk_window_buildable_interface_init)
@@ -637,7 +634,7 @@ gtk_window_measure (GtkWidget      *widget,
 {
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
-  GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
+  GtkWidget *child = priv->child;
   gboolean has_size_request = gtk_widget_has_size_request (widget);
   int title_min_size = 0;
   int title_nat_size = 0;
@@ -708,15 +705,35 @@ gtk_window_measure (GtkWidget      *widget,
 }
 
 static void
-gtk_window_add (GtkContainer *container,
-                GtkWidget    *child)
+gtk_window_compute_expand (GtkWidget *widget,
+                           gboolean  *hexpand,
+                           gboolean  *vexpand)
 {
-  /* Insert the child's css node now at the end so the order wrt. decoration_node is correct */
-  gtk_css_node_insert_before (gtk_widget_get_css_node (GTK_WIDGET (container)),
-                              gtk_widget_get_css_node (child),
-                              NULL);
+  GtkWindow *window = GTK_WINDOW (widget);
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
+  if (priv->child)
+    {
+      *hexpand = gtk_widget_compute_expand (priv->child, GTK_ORIENTATION_HORIZONTAL);
+      *vexpand = gtk_widget_compute_expand (priv->child, GTK_ORIENTATION_VERTICAL);
+    }
+  else
+    {
+      *hexpand = FALSE;
+      *vexpand = FALSE;
+    }
+}
 
-  GTK_CONTAINER_CLASS (gtk_window_parent_class)->add (container, child);
+static GtkSizeRequestMode
+gtk_window_get_request_mode (GtkWidget *widget)
+{
+  GtkWindow *window = GTK_WINDOW (widget);
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
+  if (priv->child)
+    return gtk_widget_get_request_mode (priv->child);
+  else
+    return GTK_SIZE_REQUEST_CONSTANT_SIZE;
 }
 
 static void
@@ -724,7 +741,6 @@ gtk_window_class_init (GtkWindowClass *klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
 
   quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
 
@@ -746,17 +762,16 @@ gtk_window_class_init (GtkWindowClass *klass)
   widget_class->realize = gtk_window_realize;
   widget_class->unrealize = gtk_window_unrealize;
   widget_class->size_allocate = gtk_window_size_allocate;
+  widget_class->measure = gtk_window_measure;
+  widget_class->compute_expand = gtk_window_compute_expand;
+  widget_class->get_request_mode = gtk_window_get_request_mode;
   widget_class->focus = gtk_window_focus;
+  widget_class->grab_focus = gtk_widget_grab_focus_none;
   widget_class->move_focus = gtk_window_move_focus;
-  widget_class->measure = gtk_window_measure;
   widget_class->state_flags_changed = gtk_window_state_flags_changed;
   widget_class->css_changed = gtk_window_css_changed;
   widget_class->snapshot = gtk_window_snapshot;
 
-  container_class->add = gtk_window_add;
-  container_class->remove = gtk_window_remove;
-  container_class->forall = gtk_window_forall;
-
   klass->activate_default = gtk_window_real_activate_default;
   klass->activate_focus = gtk_window_real_activate_focus;
   klass->keys_changed = gtk_window_keys_changed;
@@ -2057,6 +2072,8 @@ gtk_window_buildable_add_child (GtkBuildable *buildable,
 {
   if (type && strcmp (type, "titlebar") == 0)
     gtk_window_set_titlebar (GTK_WINDOW (buildable), GTK_WIDGET (child));
+  else if (GTK_IS_WIDGET (child))
+    gtk_window_set_child (GTK_WINDOW (buildable), GTK_WIDGET (child));
   else
     parent_buildable_iface->add_child (buildable, builder, child, type);
 }
@@ -2624,8 +2641,10 @@ gtk_window_dispose (GObject *object)
   gtk_window_set_default_widget (window, NULL);
   remove_attach_widget (window);
 
-  G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
+  g_clear_pointer (&priv->child, gtk_widget_unparent);
   unset_titlebar (window);
+
+  G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object);
 }
 
 static void
@@ -3146,7 +3165,7 @@ gtk_window_set_titlebar (GtkWindow *window,
 
   gtk_window_enable_csd (window);
   priv->title_box = titlebar;
-  /* Same reason as in gtk_window_add */
+  /* Same reason as in gtk_window_set_child */
   gtk_css_node_insert_before (gtk_widget_get_css_node (GTK_WIDGET (window)),
                               gtk_widget_get_css_node (titlebar),
                               NULL);
@@ -4319,13 +4338,12 @@ gtk_window_update_toplevel (GtkWindow *window)
 static void
 gtk_window_map (GtkWidget *widget)
 {
-  GtkWidget *child;
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+  GtkWidget *child = priv->child;
 
   GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget);
 
-  child = gtk_bin_get_child (GTK_BIN (window));
   if (child != NULL && gtk_widget_get_visible (child))
     gtk_widget_map (child);
 
@@ -4377,7 +4395,7 @@ gtk_window_unmap (GtkWidget *widget)
 {
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
-  GtkWidget *child;
+  GtkWidget *child = priv->child;
   GdkSurfaceState state;
 
   GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget);
@@ -4397,7 +4415,6 @@ gtk_window_unmap (GtkWidget *widget)
   if (priv->title_box != NULL)
     gtk_widget_unmap (priv->title_box);
 
-  child = gtk_bin_get_child (GTK_BIN (window));
   if (child != NULL)
     gtk_widget_unmap (child);
 }
@@ -4908,9 +4925,11 @@ gtk_window_unrealize (GtkWidget *widget)
   /* Icons */
   gtk_window_unrealize_icon (window);
 
-  gtk_container_forall (GTK_CONTAINER (widget),
-                        (GtkCallback) gtk_widget_unrealize,
-                        NULL);
+  if (priv->title_box)
+    gtk_widget_unrealize (priv->title_box);
+
+  if (priv->child)
+    gtk_widget_unrealize (priv->child);
 
   g_clear_object (&priv->renderer);
 
@@ -5066,12 +5085,12 @@ gtk_window_size_allocate (GtkWidget *widget,
                           int        baseline)
 {
   GtkWindow *window = GTK_WINDOW (widget);
-  GtkWidget *child;
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+  GtkWidget *child = priv->child;
   GtkAllocation child_allocation;
 
   _gtk_window_set_allocation (window, width, height, &child_allocation);
 
-  child = gtk_bin_get_child (GTK_BIN (window));
   if (child && gtk_widget_get_visible (child))
     gtk_widget_size_allocate (child, &child_allocation, -1);
 }
@@ -5432,19 +5451,6 @@ gtk_window_key_released (GtkWidget       *widget,
   return FALSE;
 }
 
-static void
-gtk_window_remove (GtkContainer *container,
-                   GtkWidget     *widget)
-{
-  GtkWindow *window = GTK_WINDOW (container);
-  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
-
-  if (widget == priv->title_box)
-    unset_titlebar (window);
-  else
-    GTK_CONTAINER_CLASS (gtk_window_parent_class)->remove (container, widget);
-}
-
 void
 gtk_window_check_resize (GtkWindow *self)
 {
@@ -5460,39 +5466,16 @@ gtk_window_check_resize (GtkWindow *self)
     gdk_profiler_end_mark (before, "size allocation", "");
 }
 
-static void
-gtk_window_forall (GtkContainer *container,
-                   GtkCallback   callback,
-                   gpointer      callback_data)
-{
-  GtkWindow *window = GTK_WINDOW (container);
-  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
-  GtkWidget *child;
-
-  child = gtk_bin_get_child (GTK_BIN (container));
-  if (child != NULL)
-    (* callback) (child, callback_data);
-
-  if (priv->title_box != NULL &&
-      priv->titlebar == NULL)
-    (* callback) (priv->title_box, callback_data);
-}
-
 static gboolean
 gtk_window_focus (GtkWidget        *widget,
-                 GtkDirectionType  direction)
+                  GtkDirectionType  direction)
 {
   GtkWindow *window = GTK_WINDOW (widget);
   GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
-  GtkBin *bin;
-  GtkContainer *container;
   GtkWidget *child;
   GtkWidget *old_focus_child;
   GtkWidget *parent;
 
-  container = GTK_CONTAINER (widget);
-  bin = GTK_BIN (widget);
-
   old_focus_child = gtk_widget_get_focus_child (widget);
 
   /* We need a special implementation here to deal properly with wrapping
@@ -5508,22 +5491,22 @@ gtk_window_focus (GtkWidget        *widget,
   if (priv->focus_widget)
     {
       if (direction == GTK_DIR_LEFT ||
-         direction == GTK_DIR_RIGHT ||
-         direction == GTK_DIR_UP ||
-         direction == GTK_DIR_DOWN)
-       {
-         return FALSE;
-       }
-      
+          direction == GTK_DIR_RIGHT ||
+          direction == GTK_DIR_UP ||
+          direction == GTK_DIR_DOWN)
+        {
+          return FALSE;
+        }
+
       /* Wrapped off the end, clear the focus setting for the toplpevel */
       parent = _gtk_widget_get_parent (priv->focus_widget);
       while (parent)
-       {
+        {
           gtk_widget_set_focus_child (parent, NULL);
-         parent = _gtk_widget_get_parent (parent);
-       }
-      
-      gtk_window_set_focus (GTK_WINDOW (container), NULL);
+          parent = _gtk_widget_get_parent (parent);
+        }
+
+      gtk_window_set_focus (window, NULL);
     }
 
   /* Now try to focus the first widget in the window,
@@ -5535,7 +5518,7 @@ gtk_window_focus (GtkWidget        *widget,
       priv->title_box != old_focus_child)
     child = priv->title_box;
   else
-    child = gtk_bin_get_child (bin);
+    child = priv->child;
 
   if (child)
     {
@@ -5546,7 +5529,7 @@ gtk_window_focus (GtkWidget        *widget,
                gtk_widget_child_focus (priv->title_box, direction))
         return TRUE;
       else if (priv->title_box == child &&
-               gtk_widget_child_focus (gtk_bin_get_child (bin), direction))
+               gtk_widget_child_focus (priv->child, direction))
         return TRUE;
     }
 
@@ -8097,10 +8080,25 @@ void
 gtk_window_set_child (GtkWindow *window,
                       GtkWidget *child)
 {
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
   g_return_if_fail (GTK_IS_WINDOW (window));
   g_return_if_fail (child == NULL || GTK_IS_WIDGET (child));
 
-  gtk_window_add (GTK_CONTAINER (window), child);
+  g_clear_pointer (&priv->child, gtk_widget_unparent);
+
+  if (child)
+    {
+      /* Insert the child's css node now at the end so the order wrt.
+       * decoration_node is correct
+       */
+      gtk_css_node_insert_before (gtk_widget_get_css_node (GTK_WIDGET (window)),
+                                  gtk_widget_get_css_node (child),
+                                  NULL);
+      priv->child = child;
+      gtk_widget_set_parent (child, GTK_WIDGET (window));
+    }
+
   g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_CHILD]);
 }
 
@@ -8115,7 +8113,9 @@ gtk_window_set_child (GtkWindow *window,
 GtkWidget *
 gtk_window_get_child (GtkWindow *window)
 {
+  GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
   g_return_val_if_fail (GTK_IS_WINDOW (window), NULL);
 
-  return gtk_bin_get_child (GTK_BIN (window));
+  return priv->child;
 }
index 8333ac91600d6397b7037c250398a66e22850e21..488a37c792cecddcef4fb22e8722e0e591e9455d 100644 (file)
@@ -32,7 +32,7 @@
 
 #include <gtk/gtkapplication.h>
 #include <gtk/gtkaccelgroup.h>
-#include <gtk/gtkbin.h>
+#include <gtk/gtkwidget.h>
 
 G_BEGIN_DECLS
 
@@ -51,7 +51,7 @@ typedef struct _GtkWindowGroupPrivate GtkWindowGroupPrivate;
 
 struct _GtkWindow
 {
-  GtkBin parent_instance;
+  GtkWidget parent_instance;
 };
 
 /**
@@ -67,7 +67,7 @@ struct _GtkWindow
  */
 struct _GtkWindowClass
 {
-  GtkBinClass parent_class;
+  GtkWidgetClass parent_class;
 
   /*< public >*/
 
index d380d44257a5bc978db42beaf59b47ba860b3eb2..101eb496416b1d3dfcfafebd80b84e0c707c629f 100644 (file)
@@ -21,7 +21,6 @@
             <child>
               <object class="GtkStack" id="content">
                 <property name="vexpand">1</property>
-                <signal name="remove" handler="assistant_remove_page_cb" swapped="no"/>
                 <child type="tab"/>
               </object>
             </child>